#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <thread>
#include <cstring>

using namespace boost::asio;

/**
 * EventFD 跨进程通信示例
 * 演示三种跨进程EventFD通信方式：
 * 1. fork()继承
 * 2. Unix Domain Socket传递文件描述符
 * 3. 共享EventFD句柄协商
 */

// 辅助函数：通过Unix Socket发送文件描述符
int send_fd(int socket_fd, int fd_to_send) {
    struct msghdr msg = {0};
    char buf[CMSG_SPACE(sizeof(fd_to_send))];
    memset(buf, '\0', sizeof(buf));
    
    // 发送一个简单的消息体
    struct iovec io = { .iov_base = (void*)"FD", .iov_len = 2 };
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    
    // 设置控制消息（包含文件描述符）
    msg.msg_control = buf;
    msg.msg_controllen = sizeof(buf);
    
    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
    
    *((int*)CMSG_DATA(cmsg)) = fd_to_send;
    
    return sendmsg(socket_fd, &msg, 0);
}

// 辅助函数：通过Unix Socket接收文件描述符
int recv_fd(int socket_fd) {
    struct msghdr msg = {0};
    char m_buffer[256];
    char c_buffer[256];
    
    struct iovec io = { .iov_base = m_buffer, .iov_len = sizeof(m_buffer) };
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_control = c_buffer;
    msg.msg_controllen = sizeof(c_buffer);
    
    if (recvmsg(socket_fd, &msg, 0) < 0) {
        return -1;
    }
    
    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
    if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
        return *((int*)CMSG_DATA(cmsg));
    }
    
    return -1;
}

/**
 * 方案1：fork()继承EventFD
 * 最简单的方式，适合父子进程通信
 */
void demonstrate_fork_inheritance() {
    std::cout << "\n=== 方案1: fork()继承EventFD ===" << std::endl;
    
    // 父进程创建eventfd
    int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    if (efd == -1) {
        perror("eventfd");
        return;
    }
    
    std::cout << "父进程创建EventFD: " << efd << std::endl;
    
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程：消费者
        std::cout << "子进程继承EventFD: " << efd << std::endl;
        
        uint64_t value;
        int count = 0;
        while (count < 3) {
            ssize_t result = read(efd, &value, sizeof(value));
            if (result == sizeof(value)) {
                std::cout << "子进程收到事件: " << value << std::endl;
                count++;
            } else if (errno != EAGAIN) {
                std::cout << "子进程读取错误: " << strerror(errno) << std::endl;
                break;
            }
            usleep(100000); // 100ms
        }
        
        close(efd);
        exit(0);
    } else {
        // 父进程：生产者
        for (int i = 1; i <= 3; i++) {
            sleep(1);
            uint64_t value = i;
            write(efd, &value, sizeof(value));
            std::cout << "父进程发送事件: " << i << std::endl;
        }
        
        wait(nullptr); // 等待子进程结束
        close(efd);
        std::cout << "fork()继承方式演示完成" << std::endl;
    }
}

/**
 * 方案2：Unix Domain Socket传递文件描述符
 * 最灵活的方式，适合任意进程间通信
 */
void demonstrate_unix_socket_fd_passing() {
    std::cout << "\n=== 方案2: Unix Socket传递FD ===" << std::endl;
    
    int sv[2]; // socketpair
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        perror("socketpair");
        return;
    }
    
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程：接收eventfd并使用
        close(sv[0]); // 关闭父进程端
        
        std::cout << "子进程等待接收EventFD..." << std::endl;
        int received_efd = recv_fd(sv[1]);
        if (received_efd < 0) {
            std::cout << "子进程接收EventFD失败" << std::endl;
            exit(1);
        }
        
        std::cout << "子进程成功接收EventFD: " << received_efd << std::endl;
        
        // 使用Boost.Asio异步处理EventFD
        io_context io;
        posix::stream_descriptor desc(io, received_efd);
        
        std::function<void()> async_read;
        async_read = [&]() {
            auto buffer = std::make_shared<uint64_t>();
            desc.async_read_some(
                boost::asio::buffer(buffer.get(), sizeof(*buffer)),
                [&, buffer](const boost::system::error_code& ec, std::size_t bytes) {
                    if (!ec && bytes == sizeof(*buffer)) {
                        std::cout << "子进程异步收到: " << *buffer << std::endl;
                        if (*buffer < 3) {
                            async_read(); // 继续读取
                        } else {
                            io.stop(); // 停止IO循环
                        }
                    }
                }
            );
        };
        
        async_read();
        io.run();
        
        close(received_efd);
        close(sv[1]);
        exit(0);
    } else {
        // 父进程：创建eventfd并发送给子进程
        close(sv[1]); // 关闭子进程端
        
        int efd = eventfd(0, EFD_NONBLOCK);
        if (efd == -1) {
            perror("eventfd");
            return;
        }
        
        std::cout << "父进程创建EventFD: " << efd << std::endl;
        
        // 发送eventfd给子进程
        if (send_fd(sv[0], efd) < 0) {
            perror("send_fd");
            return;
        }
        
        std::cout << "父进程已发送EventFD给子进程" << std::endl;
        
        // 发送事件
        for (int i = 1; i <= 3; i++) {
            sleep(1);
            uint64_t value = i;
            write(efd, &value, sizeof(value));
            std::cout << "父进程发送事件: " << i << std::endl;
        }
        
        wait(nullptr);
        close(efd);
        close(sv[0]);
        std::cout << "Unix Socket传递方式演示完成" << std::endl;
    }
}

/**
 * 方案3：共享内存协商EventFD句柄
 * 适合需要持久化EventFD信息的场景
 */
#include <sys/mman.h>
#include <fcntl.h>

struct SharedEventFdInfo {
    int eventfd_handle;
    volatile int ready_flag;
    volatile int shutdown_flag;
};

void demonstrate_shared_memory_coordination() {
    std::cout << "\n=== 方案3: 共享内存协商 ===" << std::endl;
    
    const char* shm_name = "/eventfd_demo_shm";
    
    // 创建共享内存
    int shm_fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open");
        return;
    }
    
    if (ftruncate(shm_fd, sizeof(SharedEventFdInfo)) == -1) {
        perror("ftruncate");
        return;
    }
    
    SharedEventFdInfo* shared_info = (SharedEventFdInfo*)mmap(
        nullptr, 
        sizeof(SharedEventFdInfo), 
        PROT_READ | PROT_WRITE, 
        MAP_SHARED, 
        shm_fd, 0
    );
    
    if (shared_info == MAP_FAILED) {
        perror("mmap");
        return;
    }
    
    // 初始化共享内存
    shared_info->ready_flag = 0;
    shared_info->shutdown_flag = 0;
    
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程：等待父进程设置eventfd
        std::cout << "子进程等待EventFD准备就绪..." << std::endl;
        
        while (!shared_info->ready_flag) {
            usleep(1000); // 等待1ms
        }
        
        int efd = shared_info->eventfd_handle;
        std::cout << "子进程获取到EventFD: " << efd << std::endl;
        
        // 处理事件
        uint64_t value;
        while (!shared_info->shutdown_flag) {
            ssize_t result = read(efd, &value, sizeof(value));
            if (result == sizeof(value)) {
                std::cout << "子进程读取: " << value << std::endl;
            } else if (errno != EAGAIN) {
                break;
            }
            usleep(100000); // 100ms
        }
        
        std::cout << "子进程收到关闭信号，退出" << std::endl;
        munmap(shared_info, sizeof(SharedEventFdInfo));
        close(shm_fd);
        exit(0);
    } else {
        // 父进程：创建eventfd并设置到共享内存
        int efd = eventfd(0, EFD_NONBLOCK);
        if (efd == -1) {
            perror("eventfd");
            return;
        }
        
        std::cout << "父进程创建EventFD: " << efd << std::endl;
        
        shared_info->eventfd_handle = efd;
        shared_info->ready_flag = 1; // 通知子进程
        
        std::cout << "父进程已在共享内存中设置EventFD" << std::endl;
        
        // 发送事件
        for (int i = 1; i <= 3; i++) {
            sleep(1);
            uint64_t value = i;
            write(efd, &value, sizeof(value));
            std::cout << "父进程发送事件: " << i << std::endl;
        }
        
        // 通知关闭
        sleep(1);
        shared_info->shutdown_flag = 1;
        
        wait(nullptr);
        close(efd);
        munmap(shared_info, sizeof(SharedEventFdInfo));
        close(shm_fd);
        shm_unlink(shm_name);
        std::cout << "共享内存协商方式演示完成" << std::endl;
    }
}

/**
 * 演示EventFD文件描述符的分配特性
 */
void demonstrate_fd_allocation() {
    std::cout << "\n=== EventFD文件描述符分配演示 ===" << std::endl;
    
    // 创建多个eventfd观察分配规律
    int fds[5];
    
    std::cout << "依次创建5个EventFD:" << std::endl;
    for (int i = 0; i < 5; i++) {
        fds[i] = eventfd(0, EFD_CLOEXEC);
        std::cout << "  EventFD[" << i << "] = " << fds[i] << std::endl;
    }
    
    // 关闭中间的一个
    std::cout << "\n关闭EventFD[2] = " << fds[2] << std::endl;
    close(fds[2]);
    
    // 再创建一个，观察是否重用
    int new_fd = eventfd(0, EFD_CLOEXEC);
    std::cout << "新创建的EventFD = " << new_fd << " (应该重用刚关闭的" << fds[2] << ")" << std::endl;
    
    // 清理
    for (int i = 0; i < 5; i++) {
        if (i != 2) close(fds[i]);
    }
    close(new_fd);
}

int main() {
    try {
        std::cout << "EventFD 跨进程通信完整演示" << std::endl;
        std::cout << "============================" << std::endl;
        
        demonstrate_fd_allocation();
        demonstrate_fork_inheritance();
        demonstrate_unix_socket_fd_passing();
        demonstrate_shared_memory_coordination();
        
    } catch (const std::exception& e) {
        std::cout << "error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}
